home *** CD-ROM | disk | FTP | other *** search
- Copyright (c) 1991-1993 Borland International, Inc.
- All Rights Reserved.
-
-
- CALLING DLL FUNCTIONS AND THE WINDOWS API
- -----------------------------------------
-
-
- Dynamic-link libraries (DLLs) are files containing compiled
- program code that Windows applications load and execute at
- runtime. Through DLLs, your Bladerunner application can call
- non-dBASE functions, such as C and Pascal functions.
-
- The Windows API (application programming interface) is a library
- of C functions contained in DLLs. This document introduces
- dynamic linking to dBASE programmers and shows how to call non-
- dBASE functions from DLLs and the Windows API.
-
- Contents
- --------
- I. About Libraries and Linking
- II. Calling DLL Functions
- III. Calling Windows API Functions
-
- About Libraries and Linking
- ---------------------------
-
- The terms "library" and "linking" mean different things to
- different programmers. dBASE III PLUS developers maintain
- libraries of often-used routines and incorporate them into
- applications without linking. dBASE IV developers use
- DBLINK to link compiled programs and library routines into
- one large object file.
-
- C language developers perform "static linking" when they
- create an executable file from various object modules and
- run-time libraries. Static linking occurs just once at the
- time you create an application. In contrast, Windows
- applications perform "dynamic linking" by calling routines
- and resources at run time. Dynamic linking occurs many
- times while an application is running. Since DLLs are parts
- of applications, they must be present on the disk when a
- program calls one of their routines or resources.
-
- By maintaining compiled routines and resources in separate
- files, and linking them to applications at run time:
-
- o You can share the same library among many applications,
- even among two applications running concurrently in
- Windows 386 enhanced mode.
-
- o You don't have to recompile or relink the library every
- time you build your application.
-
- o You create smaller executable files.
-
- Calling DLL Functions
- ---------------------
-
- Using DLLs is much like using procedure files. You load a DLL
- into memory before using one of its routines, then release the
- DLL when its routines are no longer needed. If the DLL file has
- a .DLL extension, or is part of the WIndows API, Bladerunner loads
- the file automatically; otherwise you need to explicitly load the
- file with LOAD DLL. (LOAD DLL is not implemented in this Alpha
- release; you can use the Windows API function LoadLibrary()
- instead.)
-
- Since DLLs are loaded at runtime, DLL files must be present on disk
- at runtime.
-
- You need to declare a "prototype" for each non-dBASE function
- before you call the function. A prototype specifies the data
- type for the function's parameters and return value. You declare
- prototypes with the EXTERN command.
-
- The need for prototypes becomes apparent when you consider
- the problem of passing parameters into functions of
- different languages. Bladerunner uses prototypes to
- convert the data types of parameters and return values
- automatically. For instance, when you call a C function,
- Bladerunner automatically converts the parameters from
- dBASE data types into C data types, and then converts the
- return values from C back into dBASE.
-
- Follow these steps to call DLL functions:
-
- 1. If the DLL file does not have a .DLL extension, and is not part
- of the Windows API, you need to load the DLL file into memory with
- LOAD DLL. (Note: In this Alpha release, LOAD DLL is not yet
- implemented. You can use the Windows API function LoadLibrary()
- instead.)
-
- If the DLL file has a .DLL extension, you can skip this step.
-
- 2. Prototype the non-dBASE functions with EXTERN.
-
- 3. Call the non-dBASE functions right in your dBASE code.
-
- 4. Remove the DLL file from memory with RELEASE DLL.
-
-
-
- EXTERN prototypes non-dBASE functions. Here is the syntax:
-
- EXTERN [CDECL] <cType1> <function name> ([<cType2>, ...])<dll name>
-
- These are the options for EXTERN:
-
- [CDECL] -- Tells dBASE to use the C language calling convention,
- instead of the default Pascal calling convention, so you can pass
- additional parameters beyond those specified in the declaration
- for this function.
-
- <cType1> -- Specifies the return value's data type. All EXTERN
- functions have to specify a return type even if it is CVOID.
-
- <cType2> -- Optionally specifies the data type of each parameter.
-
- All arguments need to match their declared type as follows:
-
- Data Type Keyword API Data Type
- --------- ------- -------------
- Numeric CWORD unsigned int (16 bit)
- Numeric CLONG unsigned long (32 bit)
- Numeric CDOUBLE double float (64 bit double)
- Character CPTR char far * (string)
- N/A CVOID void
-
- <function name> -- The name of the function in the DLL.
-
- <dll name> -- The name of the Windows .DLL that contains the
- function.
-
- Note: Most of the functionality of Windows is contained in DLL's,
- but dynamic link library code can also be present in .EXE files
- (or even in .DRV or .FON files).
-
- Example:
-
- EXTERN CWORD MessageBox(CWORD,CPTR,CPTR,CWORD) user.exe
-
- Calling Windows API Functions
- -----------------------------
-
- The API function must be prototyped before you call it from
- Bladerunner. You can prototype the API functions at the Command
- window, in the .PRG, or in an #include file. Once an API
- function has been prototyped, it is available as if it were an
- internal Bladerunner function, until you end that Bladerunner
- session.
-
- Execute the API function like any dBASE function after you have
- prototyped it. API functions can be called directly or they can
- be part of a dBASE expression or function. Also, dBASE functions
- can be put inside API functions.
-
- Example:
-
- EXTERN CWORD MessageBox(CWORD,CPTR,CPTR,CWORD) user.exe
- ? MessageBox(0,"My Text","From Windows",17)
-
- or
-
- pressed = MessageBox(0,"My Text","From Windows",17)
-
- or
-
- ? MessageBox(0,"My Text","From Windows",HTOI("00011"))
-
- This displays a Windows MessageBox in the middle of the screen,
- with the Title: "From Windows" and the Message: "My Text" and two
- buttons: "OK" "CANCEL" and the ICON: "STOP". It returns the
- value for the button pressed 1= OK , 2 = CANCEL.
-
- Note: You can execute the function without the ? (print) command,
- just by putting the function name with its arguments on the
- command line by itself, but you won't display the return value.
-
- Example:
-
- EXTERN CWORD MessageBox(CWORD,CPTR,CPTR,CWORD) user.exe
- MessageBox(0,"My Text","From Windows",17)
-
- Displays MessageBox as above but without displaying the return
- value for the button pressed.
-
- The windows API functions can be prototyped and executed right at
- the command window in Bladerunner. You do not have to load any
- special header file or .DLL to access the windows API functions.
-
- API Window Handles
-
- API window handles are numbers, 16 bit integers (CWORD), like
- file handles in DOS, that are assigned to every window. To get
- the Windows handle of dBASEWIN.EXE you can use the following
- approaches:
-
- Example A:
-
- hDBW = _APP.FRAMEWIN.HWND
-
- The variable hDBW now holds the Windows handle to dBASEWIN.EXE
- FRAMEWIN (the main window of dBASEWIN.EXE).
-
- Example B:
-
- EXTERN CWORD GetActiveWindow( ) user.exe
- hDBW = GetActiveWindow( )
-
- The variable hDBW now holds the windows handle of the active
- window. If you type the above in the Command window, the
- variable hDBW will hold the Windows handle of the FRAMEWIN of
- dBASEWIN.EXE, as in Example A, above.
-
- Example C:
-
- EXTERN CWORD GetFocus() user.exe
- hDBW = GetFocus()
-
- The variable hDBW now holds the windows handle of the window with
- input focus. If you type the above in the Command window, the
- variable hDBW will hold the Windows handle of the Command window.
- But if you DEFINE a window and ACTIVATE the window, then issue
- the GetFocus() function in your program, it will return the
- handle of the window you ACTIVATED.
-
- Windows API Constants
-
- Windows has many constants defined as integers, like the cursors
- below.
-
- Example:
-
- #define IDC_ARROW (32512)
- #define IDC_IBEAM (32513)
- #define IDC_WAIT (32514)
- #define IDC_CROSS (32515)
- #define IDC_UPARROW (32516)
- #define IDC_SIZE (32640)
- #define IDC_ICON (32641)
- #define IDC_SIZENWSE (32642)
- #define IDC_SIZENESW (32643)
- #define IDC_SIZEWE (32644)
- #define IDC_SIZENS (32645)
- EXTERN CWORD LoadCursor(CWORD,CWORD) user.exe
- EXTERN CWORD SetCursor(CWORD) user.exe
- orgcsr = SetCursor(LoadCursor(0, IDC_ICON))
- FOR x = 1 to 210000
- NEXT
- SetCursor(orgcsr)
-
- HEX Numbers
-
- Windows has many constants defined as hex numbers.
-
- Example:
-
- #define MB_OK 0x0000
- #define MB_OKCANCEL 0x0001
- #define MB_ABORTRETRYIGNORE 0x0002
- #define MB_YESNOCANCEL 0x0003
- #define MB_ICONHAND 0x0010
- #define MB_ICONQUESTION 0x0020
- #define MB_ICONEXCLAMATION 0x0030
- #define MB_ICONASTERISK 0x0040
- EXTERN CWORD MessageBox(CWORD,CPTR,CPTR,CWORD) user.exe
- MessageBox(0,"My Text","From Windows",HTOI("0x0022"))
-
- The dBASE functions for working with hex numbers are:
-
- HTOI() Takes a hex number as a string and returns an
- integer.
- ITOH() Takes an integer and returns a hex number as a
- string.
-
- Bits
-
- Many DLL functions interpret individual bits in an integer
- argument or return value. We have added several new functions to
- Bladerunner for working with bits. Bits are numbered in an
- integer from the least significant bit (rightmost) to the most
- significant bit (leftmost). Bit numbering starts at 0 (see
- example below).
-
- Most Least
- Significant Significant
- 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- Example:
-
- * gVer.prg
- #define HiWord(x) (bitrshift(bitand(x,4294901760),16))
- #define LoWord(x) (bitand(x,65535))
- #define HiByte(x) (ltrim(str(bitrshift(bitand(x,65280),8))))
- #define LoByte(x) (ltrim(str(bitand(x,255))))
- EXTERN CLONG GetVersion( ) krnl386.exe
- z=GetVersion( )
- RETURN "DOS version;
- "+HiByte(HiWord(z))+"."+LoByte(HiWord(z))+ ;
- ", Windows version"+LoByte(LoWord(z))+"."+HiByte(LoWord(z))
-
- Note: The above code example, and several others, are included
- with the sample code provided with this Alpha release.
-
- The new dBASE bit functions are: BitAND(), BitLshift(),
- BitRshift(), BitOr(), BitXor(),and BitSet().
-
- Windows API Strings
-
- Many API functions take a string as an argument. Some API
- functions only want a Pointer (a reference) to a string that the
- function can fill with the returned information. In this case
- you need to make the string large enough to hold the result (some
- also require you to pass the length of the string as a argument).
-
- Example:
-
- dBWhand = _APP.FRAMEWIN.HWND
- EXTERN CWORD GetWindowText(CWORD,CPTR,CWORD) user.exe
- winTitle = SPACE(80)
- && first make empty string to be filled
- lenTitle = GetWindowText(dBWhand,winTitle,80)
- ? winTitle
-
- Note: With Bladerunner's object-oriented language extensions you
- can get the same information with this command:
-
- ? _APP.FRAMEWIN.CAPTION
-
-